<?php

$script_dir = dirname( __FILE__ );

require_once( "$script_dir/Models.php" );

// Credits that go into Special:Version page
$wgExtensionCredits['parserhook'][] = array(
    'name' => 'Grid Test',
    'author' => 'Gabi Purcaru, Claudiu Soroiu, Mihaela Runceanu, Adrian Runceanu',
    'description' => 'Extension for making grid tests.',
);

// register hooks
$wgHooks['ParserFirstCallInit'][] = 'gtInit';
$wgHooks['LanguageGetMagic'][]    = 'gtQuestionMagic';
$wgHooks['LoadExtensionSchemaUpdates'][] = 'gtUpdateSchema';
$wgHooks['ArticleViewHeader'][] =  'gtCheckForTestSubmit';

$wgAutoloadClasses['SpecialGridTestVerify'] = "$script_dir/SpecialGridTestVerify.php";
$wgSpecialPages['GridTest'] = 'SpecialGridTestVerify';
$wgSpecialPageGroups['GridTest'] = 'GridTest';
$wgExtensionMessagesFiles['GridTest'] = "$script_dir/GridTest.i18n.php";



function gtUpdateSchema( $updater=null ) {
    $script_dir = dirname( __FILE__ );
    $tables = array(
        'test' => 'testSchema.sql',
        'submitted_test' => 'submitted_testSchema.sql',
        'submitted_answer' => 'submitted_answerSchema.sql',
    );

    foreach( $tables as $name => $file ) {
        if( $updater === null ) {
            $wgExtNewTables[] = array( $name, $script_dir . '/' . $file );
        } else {
            $updater->addExtensionUpdate( array(
                'addTable',
                $name,
                $script_dir . '/' . $file,
                true
            ) );
        }
    }

    return true;
}


/**
 *  Registers tag and parser hooks
 */
function gtInit( Parser &$parser ) {
    $parser->setHook( 'grila', 'gtRender' );
    $parser->setFunctionHook( 'question', 'gtQuestionRender', SFH_NO_HASH );
    return true;
}

// used to grab all questions in a grid test
$gtQuestions = array();

// this is true when the user submitted a grid test
$gtTestSubmitted = false;

/**
 *  Renders <grila> tags
 */
function gtRender( $input, array $args, Parser $parser, PPFrame $frame ) {
    global $gtQuestions;
    global $gtTestSubmitted;

    if( $gtTestSubmitted ) {
        $output = "Testul a fost trimis.";
        return $output;
    }
    
    $output  = '<form action="#" method="post">';
    $output .= '<h4>Test grilă ';
    if( isset( $args['titlu'] ) ) {
        $output .= "- {$args['titlu']}";
    }
    $output .= '</h4>';

    // replace extra whitespace between closing }} tags and opening {{ tags, 
    // because it leads to extra useless space
    $input = preg_replace( "~(?!}}|^)\s+(?={{|$)~m", "", $input );

    // clear gtQuestions, because it may span multiple <grila> tags
    $gtQuestions = array();

    // we also want wiki markup inside this tag
    $output .= trim( $parser->recursiveTagParse( $input, $frame ) );

    $testName = isset( $args['titlu'] ) ? $args['titlu'] : null;

    // save gtQuestions
    $test_id = gtSaveGridTest( $gtQuestions, $testName );

    $output .= '<br/>';
    $output .= "<input type='hidden' name='test_id' value='$test_id' />";
    $output .= '<input type="hidden" name="x-action-type" value="GridTest" />';
    $output .= '<input type="submit" value="&raquo;Trimite" />';
    $output .= '</form>';

    return $output;
}


/**
 *  Registers magic words for answers
 */
function gtQuestionMagic( $magicWords, $langCode ) {
    $magicWords['question'] = array( 0, 'question', 'intrebare', 'întrebare' );
    return true;
}

/**
 *  Renders the question HTML
 */
function gtQuestionRender() {
    global $gtQuestions;

    // preparations
    $script_dir = dirname( __FILE__ );
    $args = func_get_args();
    $parser = $args[0];

    $parserInstance = new Parser();
    $question = $parserInstance->parse( $args[1], new Title(), new ParserOptions() )->getText();
    $question_id = md5( $question );
    $others = array_slice( $args, 2 );
    $answers = array();
    $modifiers = array();

    // arguments parsing
    foreach( $others as $item ) {
        // if we have an '=' but not '\=' or '=>', it's a modifier 
        if( preg_match( '/^(.*?)(?<!\\\)=(?!>)(.*)$/', $item, $matches ) ) { 
            $modifier = trim( $matches[1] );
            $value = trim( $matches[2] );
            $modifiers[$modifier] = $value;
        } else { // otherwise it's an answer
            preg_match( '/^(.*?)([^\\\]=>(.*))?$/', $item, $matches );
            $answer = htmlentities( trim( $matches[1] ) );
            // $matches[2] e grupul optional, abia [3] e ce ne trebuie
            if( isset( $matches[3] ) ) { 
                $points = (double)trim( $matches[3] );
            } else {
                $points = 0; // score defaults to 0 if not given
            }
            $answers[] = array( 
                'text' => $answer,
                'points' => $points
            );
        } 
    }

    $gtQuestions[] = array(
        'question' => $question,
        'answers' => $answers,
        'modifiers' => $modifiers
    );

    // render HTML
    ob_start();
    $valid_types = array(
        'checkbox', 'radio', 'text', 'upload', 'longtext'
    );
    if( !isset( $modifiers['tip'] )  || !in_array( $modifiers['tip'], $valid_types ) ) {
        $tip = 'checkbox'; // default value 
    } else {
        $tip = $modifiers['tip'];
    }
    require( "{$script_dir}/templates/question_{$tip}.php" );
    $html = ob_get_clean();

    // it seems that MW puts extra <p>'s whenever it sees extra whitespace
    // so we need to get rid of whitespace between html tags
    // copy-paste from http://www.lonhosford.com/lonblog/2011/01/07/php-simplexml-load-xml-file-preserve-cdata-remove-whitespace-between-nodes-and-return-json/
    $clean_html = preg_replace( '~\s*(<([^>]*)>[^<]*</\2>|<[^>]*>)\s*~', '$1', $html );

    return array(
        trim( $clean_html ),
        'isHTML' => true, // make sure that MW will not html-escape code in here
        'noparse' => true, // this code does not need further parsing 
    );
}

function gtCheckForTestSubmit() {
    if( isset( $_POST['x-action-type'] ) && $_POST['x-action-type'] == 'GridTest' ) {
        gtSubmitGridTest( $_POST );
    }
    return true;
}


/**
 *  Submits a test to the database
 */
function gtSubmitGridTest( $post ) {
    global $gtTestSubmitted;
    global $wgUser;

    // checks if uer is logged in
    if( !$wgUser->isLoggedIn() ) {
        return false;
    }

    gtSaveSubmittedTest( $post );
    
    $gtTestSubmitted = true;
}
